/*
  Applicast API Extension/Utility Library
  Base Utilities: Node, $, Super-Simple event subsys...

  (c) 2009 Estanislau Trepat / ILERRED, S.L.

  Applicast API Extension Library is freely
  distributable under the terms of an MIT-style license.
*/

var Node = Class.create({
  initialize: function(node) {
    this.node = this._get$(node);

    if ( typeof node === 'string' )
      this.name = node;

    this.childNodes = [];
  },

  getName: function() {
    if ( typeof this.name === 'undefined' )
      this.name = getName(this.node);
    return this.name;
  },

  isVisible: function() {
    if ( typeof this.visible === 'undefined' )
      this.visible = ((isVisible(this.node) == 0) ? false : true);

    return this.visible;
  },

  setVisible: function(visible) {
    this.visible = visible;
    setVisible(this.node, this.visible ? 1 : 0);
    return this;
  },

  toggle: function() {
    this.setVisible(!this.isVisible());
    return this;
  },

  getPos: function() {
    if ( typeof this.position === 'undefined' )
      this.position = {x: getPosX(this.node), y: getPosY(this.node)};

    return Object.clone(this.position);
  },

  setPos: function(newX, newY) {
    if ( typeof this.position === 'undefined' )
      this.position = {x: 0, y:0};

    this.position.x = newX;
    this.position.y = newY;
    setPos(this.node, this.position.x, this.position.y);
    return this;
  },

  getColor: function() {
    if ( typeof this.color === 'undefined' )
      this.position = {x: getPosX(this.node), y: getPosY(this.node)};

    return Object.clone(this.color);
  },

  setColor: function(rgb, alpha) {
    if ( typeof this.color === 'undefined' )
      this.color = {rgb: '000000', alpha: 255};

    this.color.rgb = rgb;
    this.color.alpha = alpha;
    setRGB(this.node, rgb);
    setAlpha(this.node, alpha);
    return this;
  },

  setColorRGB: function(red, green, blue, alpha) {
    var rgb = [red.toColorPart(), green.toColorPart(), blue.toColorPart()].join('');
    this.setColor(rgb, alpha);
    return this;
  },

  setAlpha: function(alpha) {
    if ( typeof this.color === 'undefined' )
      this.color = {rgb: '000000', alpha: 255};

    this.color.alpha = alpha;
    setAlpha(this.node, alpha);
    return this;
  },

  loadImage: function(path) {
    this.src = path;
    loadImage(this.node, path);
    return this;
  },

  isImageLoaded: function() {
    if ( typeof this.src === 'undefined' )
      return false;

    return (isImageLoaded(this.node) ? true : false);
  },

  destroyImage: function() {
    destroyImage(this.node);
    return this;
  },

  getImageSrc: function() {
    if ( typeof this.src === 'undefined' )
      return '';
    return this.src;
  },

  getDimensions: function() {
    if ( typeof this.dimensions === 'undefined' )
      this.dimensions = {w: getW(this.node), h: getH(this.node)};

    return Object.clone(this.dimensions);
  },

  setDimensions: function(width, height) {
    if ( typeof this.dimensions === 'undefined' )
      this.dimensions = {w: 0, h: 0};

    this.dimensions.w = width;
    this.dimensions.h = height;
    setW(this.node, this.dimensions.w);
    setH(this.node, this.dimensions.h);
    return this;
  },

  getStr: function() {
    this.text = getStr(this.node) || '';
    return this.text;
  },

  setStr: function(text, shadow, options) {
    this.text = text;
    setStr(this.node, this.text);
    if ( shadow ) {
      // low level here: speed, speed, speed...
      var shadowNode = this._get$(this.getName() + '_shadow');
      if ( shadowNode ) {
        // we need current node position
        var currentPos = this.getPos();

        var shadowOptions = {
          offsetX: 1,
          offsetY: 1,
          color: '000000',
          alpha: 255
        };
        Object.extend(shadowOptions, options || { });

        setStr(shadowNode, text);
        setPos(shadowNode, currentPos.x + shadowOptions.offsetX, currentPos.y + shadowOptions.offsetY);
        setRGB(shadowNode, shadowOptions.color);
        setAlpha(shadowNode, shadowOptions.alpha);
        setVisible(shadowNode, this.isVisible() ? 1 : 0);
      }
    }
    return this;
  },

  getLines: function() {
    if ( typeof this.text === 'undefined' )
      this.getStr();

    if ( this.text.strip() === '' ) return 0;
    return getLines(this.node);
  },

  pageDown: function() {
    if ( typeof this.text === 'undefined' )
      this.getStr();

    if ( this.text !== '' )
      pageDown(this.node);
    return this;
  },

  pageUp: function() {
    if ( typeof this.text === 'undefined' )
      this.getStr();

    if ( this.text !== '' )
      pageUp(this.node);
    return this;
  },

  lineDown: function() {
    if ( typeof this.text === 'undefined' )
      this.getStr();

    if ( this.text !== '' )
      lineDown(this.node);
    return this;
  },

  lineUp: function() {
    if ( typeof this.text === 'undefined' )
      this.getStr();

    if ( this.text !== '' )
      lineUp(this.node);
    return this;
  },

  isChildNode: function(node) {
    node = this._get$(node);
    if ( !node )
      return false;
    return getChildNode(this.node, getName(node)) ? true : false;
  },

  getChild: function(node) {
    if ( !this.isChildNode(node) )
      return false;

    node = this._get$(node);
    if ( !node )
      return false;
    return $(node);
  },

  _get$: function(node) {
    if ( typeof node === 'string' ) return getNode(node);
    return node;
  }
});

// Here comes the almighty $() function!
// AppliCast(tm) ready ;)
function $() {
  if ( arguments.length === 1 ) return new Node(arguments[0]);

  var nodes = [];
  for(var i=0, m=arguments.length; i < m; ++i)
    nodes.push(new Node(arguments[i]));
  return nodes;
}

// Simple (I mean, VERY simple) Event simulation for AppliCast(tm) widgets
// Please, don't blame me for this...
var Event = new Object();
Object.extend(Event, {
  KEY_CONFIRM: 0,
  KEY_UP: 100,
  KEY_DOWN: 101,
  KEY_LEFT: 102,
  KEY_RIGHT: 103,
  KEY_BLUE: 200,
  KEY_RED: 201,
  KEY_GREEN: 202,
  KEY_YELLOW: 203,

  observers: [],

  observe: function(event, observer) {
    if ( typeof this.observers['on' + event] === 'undefined' )
      this.observers['on' + event] = observer;
  },

  fire: function(event, data) {
    if ( typeof this.observers['on' + event] !== 'undefined' )
      this.observers['on' + event](data);
  },

  clearObservers: function() {
    this.observers.clear();
  }
});

// Widget Modes
var WidgetModes = ['Error', 'Loading', 'Normal/Focus', 'Active', 'Full-Screen'];
var WidgetMode = new Object();
Object.extend(WidgetMode, {
  ERROR: 0,
  LOADING: 1,
  NORMALFOCUS: 2,
  ACTIVE: 3,
  FULLSCREEN: 4
});